<?php

namespace app\common\logic\mall;

use addons\litestore\model\Litestoregoodsspec;
use addons\litestore\model\Litestoreorder;
use addons\litestore\model\Litestoreordergoods;
use app\admin\model\litestore\Litestoregoods;
use app\api\validate\mall\Refund;
use app\common\model\mall\GoodsEvaluate;
use app\common\model\mall\RefundLog;
use app\common\model\meet\Config;
use EasyWeChat\Factory;
use think\Db;

class Order
{
    protected $error = '';

    /**
     * 提交退款申请
     */
    public function refundOrderSubmimt($data, $user_info)
    {
        $validate = new Refund();

        $check = $validate->check($data);

        if (!$check) {
            $this->error = __($validate->getError());
            return false;
        }

        $order_goods_info = Litestoreordergoods::with(['spec', 'goods'])->where(['id' => $data['id'], 'user_id' => $user_info['id']])->find();

        if (empty($order_goods_info)) {
            $this->error = __('No results were found');
            return false;
        }

        if ($order_goods_info['refund_status'] > 0) {
            $this->error = __('Refunded, please do not repeat the operation');
            return false;
        }

        $order_model = new Litestoreorder();
        $order_info = $order_model->where('id', '=', $order_goods_info['order_id'])->find();

        if (empty($order_info)) {
            $this->error = __('No results were found');
            return false;
        }

        if ($order_info['pay_status'] != 20) {
            $this->error = __('The order has not been paid and cannot be refunded');
            return false;
        }

        if ($order_info['order_status'] >= 30) {
            $this->error = __('The order has been completed and cannot be refunded');
            return false;
        }

        Db::startTrans();
        try {
            $model = new \app\common\model\mall\Refund();

            $insert = [
                'user_id' => $user_info['id'],
                'order_id' => $order_goods_info['order_id'],
                'order_goods_id' => $order_goods_info['id'],
                'refund_no' => $model->createRefundNo(),
                'refund_money' => $order_goods_info['total_price'],
                'refund_type' => $data['refund_type'],
                'refund_reason' => $data['refund_reason'],
                'refund_images' => isset($data['refund_images']) ? $data['refund_images'] : '',
                'refund_explain' => isset($data['refund_explain']) ? $data['refund_explain'] : '',
                'refund_status' => $model::REFUND_STATUS_APPLY
            ];

            $model->save($insert);

            $order_goods_info->save(['refund_status' => 1]);

            $log_model = new RefundLog();

            //写入日志
            $log = [
                'order_goods_id' => $order_goods_info['id'],
                'refund_id' => $model->id,
                'refund_status' => $log_model::REFUND_STATUS_APPLY,
                'operate_type' => $log_model::OPERATE_TYPE_BUYER,
                'operate_id' => $user_info['id'],
                'operate_name' => $user_info['nickname'],
                'operate_content' => '提交申请'
            ];

            $log_model->save($log);

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error = $e->getMessage();
            return false;
        }

        return true;
    }

    /**
     * 取消退款申请
     */
    public function refundCancel($id, $user_info)
    {
        if (empty($id)) {
            $this->error = __('Invalid parameters');
            return false;
        }

        $model = new \app\common\model\mall\Refund();

        $refund_info = $model->where('id', '=', $id)->find();

        if (empty($refund_info)) {
            $this->error = __('No results were found');
            return false;
        }

        if ($refund_info['refund_status'] != $model::REFUND_STATUS_APPLY) {
            $this->error = __('Operation failed');
            return false;
        }

        Db::startTrans();
        try {
            $refund_info->save(['refund_status' => $model::REFUND_STATUS_CANCEL]);

            (new Litestoreordergoods())->save(['refund_status' => 0], ['id' => $refund_info['order_goods_id']]);

            $log_model = new RefundLog();

            //写入日志
            $log = [
                'order_goods_id' => $refund_info['order_goods_id'],
                'refund_id' => $refund_info['id'],
                'refund_status' => $log_model::REFUND_STATUS_CANCEL,
                'operate_type' => $log_model::OPERATE_TYPE_BUYER,
                'operate_id' => $user_info['id'],
                'operate_name' => $user_info['nickname'],
                'operate_content' => '取消申请'
            ];

            $log_model->save($log);

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error = $e->getMessage();
            return false;
        }

        return true;
    }

    /**
     * 删除退款申请记录
     */
    public function refundDel($id)
    {
        if (empty($id)) {
            $this->error = __('Invalid parameters');
            return false;
        }

        $model = new \app\common\model\mall\Refund();

        $refund_info = $model->where('id', '=', $id)->find();

        if (empty($refund_info)) {
            $this->error = __('No results were found');
            return false;
        }

        if (!in_array($refund_info['refund_status'], [$model::REFUND_STATUS_CANCEL, $model::REFUND_STATUS_REFUSE, $model::REFUND_STATUS_COMPLETE])) {
            $this->error = __('Operation failed');
            return false;
        }

        return $refund_info->save(['is_del' => $model::IS_DEL_YES, 'del_time' => time()]);
    }

    /**
     * 退款订单-用户发货
     */
    public function refundDeliveryByUser($data, $user_info)
    {
        if (empty($data['id'])) {
            $this->error = __('Parameter %s can not be empty', 'id');
            return false;
        }

        if (empty($data['express_company'])) {
            $this->error = __('Parameter %s can not be empty', 'express_company');
            return false;
        }

        if (empty($data['express_no'])) {
            $this->error = __('Parameter %s can not be empty', 'express_no');
            return false;
        }

        $model = new \app\common\model\mall\Refund();

        $refund_info = $model->where('id', '=', $data['id'])->find();

        if (empty($refund_info)) {
            $this->error = __('No results were found');
            return false;
        }

        if ($refund_info['refund_status'] != $model::REFUND_STATUS_WAIT_BUYER) {
            $this->error = __('Operation failed');
            return false;
        }

        Db::startTrans();
        try {
            $refund_info->save(['express_company' => $data['express_company'], 'express_no' => $data['express_no'], 'refund_status' => $model::REFUND_STATUS_WAIT_SELLER]);

            $log_model = new RefundLog();

            //写入日志
            $log = [
                'order_goods_id' => $refund_info['order_goods_id'],
                'refund_id' => $refund_info['id'],
                'refund_status' => $log_model::REFUND_STATUS_WAIT_SELLER,
                'operate_type' => $log_model::OPERATE_TYPE_BUYER,
                'operate_id' => $user_info['id'],
                'operate_name' => $user_info['nickname'],
                'operate_content' => '寄回商品'
            ];

            $log_model->save($log);

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error = $e->getMessage();
            return false;
        }

        return true;
    }

    public function refundVerify($refund_info, $admin_info, $type = 0, $params = [], $memo = '')
    {
        $refund_model = new \app\common\model\mall\Refund();
        if ($refund_info->refund_status > $refund_model::REFUND_STATUS_APPLY) {
            $this->error = __('Operated, please do not repeat the operation');
            return false;
        }

        Db::startTrans();
        try {
            $log_model = new RefundLog();
            if ($type == 1) {   //拒绝
                $data = [
                    'refund_status' => $refund_model::REFUND_STATUS_REFUSE,
                    'refund_refuse_reason' => $memo
                ];

                $refund_info->save($data);

                (new Litestoreordergoods())->save(['refund_status' => 0], ['id' => $refund_info['order_goods_id']]);

                //写入日志
                $log = [
                    'order_goods_id' => $refund_info['order_goods_id'],
                    'refund_id' => $refund_info['id'],
                    'refund_status' => $log_model::REFUND_STATUS_REFUSE,
                    'operate_type' => $log_model::OPERATE_TYPE_SELLER,
                    'operate_id' => $admin_info['id'],
                    'operate_name' => $admin_info['username'],
                    'operate_content' => '商家拒绝申请'
                ];

                $log_model->save($log);
            } else {      //通过
                $refund_status = $refund_info['refund_type'] == $refund_model::REFUND_TYPE_REFUND ? $refund_model::REFUND_STATUS_COMPLETE : $refund_model::REFUND_STATUS_WAIT_BUYER;

                $data = [
                    'refund_status' => $refund_status,
                    'refund_time' => $refund_info['refund_type'] == $refund_model::REFUND_TYPE_REFUND ? time() : 0
                ];

                if ($refund_info['refund_type'] == $refund_model::REFUND_TYPE_REFUND_RETURN) {
                    $data['receive_name'] = $params['receive_name'];
                    $data['receive_mobile'] = $params['receive_mobile'];
                    $data['receive_address'] = $params['receive_address'];
                }

                $refund_info->save($data);

                $operate_content = '商家审核通过';
                if ($refund_info['refund_type'] == $refund_model::REFUND_TYPE_REFUND) {
                    //退款类型为仅退款时-退款金额原路返回用户账户
                    $this->refundMoneyByWechat($refund_info);
                    $operate_content = '退款成功';
                }

                //写入日志
                $log = [
                    'order_goods_id' => $refund_info['order_goods_id'],
                    'refund_id' => $refund_info['id'],
                    'refund_status' => $refund_status,
                    'operate_type' => $log_model::OPERATE_TYPE_SELLER,
                    'operate_id' => $admin_info['id'],
                    'operate_name' => $admin_info['username'],
                    'operate_content' => $operate_content
                ];

                $log_model->save($log);
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error = $e->getMessage();
            return false;
        }

        return true;
    }

    /**
     * 退款申请-完成
     */
    public function refundComplete($refund_info, $admin_info)
    {
        if ($refund_info['refund_status'] != \app\common\model\mall\Refund::REFUND_STATUS_WAIT_SELLER) {
            $this->error = __('Operation failed');
            return false;
        }

        Db::startTrans();
        try {
            $refund_info->save(['refund_status' => \app\common\model\mall\Refund::REFUND_STATUS_COMPLETE]);

            $this->refundMoneyByWechat($refund_info);

            $log_model = new RefundLog();

            //写入日志
            $log = [
                'order_goods_id' => $refund_info['order_goods_id'],
                'refund_id' => $refund_info['id'],
                'refund_status' => $log_model::REFUND_STATUS_COMPLETE,
                'operate_type' => $log_model::OPERATE_TYPE_SELLER,
                'operate_id' => $admin_info['id'],
                'operate_name' => $admin_info['username'],
                'operate_content' => '退款成功'
            ];

            $log_model->save($log);

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error = $e->getMessage();
            return false;
        }

        return true;
    }

    public function refundMoneyByWechat($refund_info)
    {
        $config = Config::getPayConfig();

        $config['notify_url'] = '';

        $app = Factory::payment($config);

        $total_fee = (int)(string)($refund_info['refund_money'] * 100);//订单支付金额
        $refund_fee = (int)(string)($refund_info['refund_money'] * 100);//退款金额

        $result = $app->refund->byTransactionId($refund_info->order_info->transaction_id, $refund_info['refund_no'], $total_fee, $refund_fee, ['refund_desc' => '商品：' . $refund_info->goods->goods_name . '退款']);

        if ($result["return_code"] === 'FAIL') {
            throw new \Exception($result["return_msg"]);
        }

        if ($result["result_code"] === 'FAIL') {
            throw new \Exception($result["err_code_des"]);
        }

        (new Litestoreordergoods())->save(['refund_status' => 2], ['id' => $refund_info['order_goods_id']]);

        (new Litestoreorder())->where(['id' => $refund_info['order_id']])->setInc('refund_money', $refund_info['refund_money']);

        //订单商品数量
        $order_goods_count = (new Litestoreordergoods())->where('order_id', '=', $refund_info['order_id'])->count();

        //订单商品退款已完成数量
        $order_refund_count = (new \app\common\model\mall\Refund())->where(['order_id' => $refund_info['order_id'], 'refund_status' => \app\common\model\mall\Refund::REFUND_STATUS_COMPLETE])->count();

        if ($order_goods_count == $order_refund_count) {
            (new Litestoreorder())->save(['refund_status' => 1, 'order_status' => 20], ['id' => $refund_info['order_id']]);
        }
    }

    public function evaluateSubmit($data, $user_info)
    {
        if (empty($data['order_id'])) {
            $this->error = __('Parameter %s can not be empty', 'order_id');
            return false;
        }

        if (empty($data['order_goods_list'])) {
            $this->error = __('Parameter %s can not be empty', 'order_goods_list');
            return false;
        }

        if (empty($data['delivery_service'])) {
            $this->error = __('Parameter %s can not be empty', 'delivery_service');
            return false;
        }

        if (empty($data['service_attitude'])) {
            $this->error = __('Parameter %s can not be empty', 'service_attitude');
            return false;
        }

        $order_info = Litestoreorder::get($data['order_id']);

        if (empty($order_info)) {
            $this->error = __('No results were found');
            return false;
        }

        if ($order_info['order_status'] != 30) {
            $this->error = __('Operation failed');
            return false;
        }

        if ($order_info['evaluate_status'] == 1) {
            $this->error = __('The order has been evaluated, please do not repeat the operation');
            return false;
        }

        $order_goods_list = json_decode(htmlspecialchars_decode($data['order_goods_list']), true);

        if (!is_array($order_goods_list) || count($order_goods_list) <= 0) {
            $this->error = __('Product information cannot be empty');
            return false;
        }

        Db::startTrans();
        try {
            $evaluate_data = [];
            $order_goods_model = new Litestoreordergoods();

            foreach ($order_goods_list as $value) {
                $order_goods_info = $order_goods_model->with(['spec'])->where(['id' => $value['id'], 'order_id' => $order_info['id']])->find();
                if (empty($order_goods_info)) {
                    throw new \Exception(__('Order item does not exist'));
                }

                (new GoodsEvaluate())->save([
                    'user_id' => $user_info['id'],
                    'nickname' => $user_info['nickname'],
                    'avatar' => $user_info['avatar'],
                    'order_id' => $order_goods_info['order_id'],
                    'order_goods_id' => $order_goods_info['id'],
                    'goods_id' => $order_goods_info['goods_id'],
                    'spec_sku_id' => $order_goods_info['spec_sku_id'],
                    'goods_name' => $order_goods_info['goods_name'],
                    'goods_spec_image' => $order_goods_info['spec']['spec_image'] ? $order_goods_info['spec']['spec_image'] : explode(',', $order_goods_info['images'])[0],
                    'goods_spec_id' => $order_goods_info['goods_spec_id'],
                    'goods_attr' => $order_goods_info['goods_attr'],
                    'goods_price' => $order_goods_info['goods_price'],
                    'goods_no' => $order_goods_info['goods_no'],
                    'content' => isset($value['content']) ? $value['content'] : '',
                    'images' => isset($value['images']) ? $value['images'] : '',
                    'is_anonymous' => $data['is_anonymous'],
                    'scores' => $value['scores'],
                    'delivery_service' => $data['delivery_service'],
                    'service_attitude' => $data['service_attitude'],
                    'status' => GoodsEvaluate::STATUS_NORMAL
                ]);

                (new Litestoregoods())->where('goods_id', $order_goods_info['goods_id'])->setInc('evaluate_nums', 1);

                (new Litestoregoodsspec())->where('goods_spec_id', $order_goods_info['goods_spec_id'])->setInc('evaluate_nums', 1);
            }

            $order_info->save(['evaluate_status' => 1]);

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error = $e->getMessage();
            return false;
        }

        return true;
    }

    public function getError()
    {
        return $this->error;
    }
}